package br.gov.cemaden.cliente.cptec.metar;

import br.gov.cemaden.library.model.alerta.Direcao;
import br.gov.cemaden.library.model.alerta.IntensidadeChuva;
import br.gov.cemaden.library.model.observacao.Metar;
import br.gov.cemaden.library.util.Converter;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author alan
 */
public class XMLReader extends DefaultHandler{
    
    private final InputStream xml;
    private final Metar metar;
    private String campo;
    
    private final Logger logger;
    private final Marker FINAL;
    
    public XMLReader(InputStream stream){
        
        this.xml = stream;
        this.metar = new Metar();
        this.logger = LoggerFactory.getLogger(XMLReader.class);
        this.FINAL = MarkerFactory.getMarker("FINAL");
        
        parseDocument();
    }
    
    private void parseDocument(){
        
        SAXParserFactory factory = SAXParserFactory.newInstance();        
        try{
            SAXParser parser = factory.newSAXParser();
            parser.parse(xml, this);
        }
        catch(ParserConfigurationException ex){
            logger.error(FINAL, "", ex);
        }
        catch(SAXException ex){
            logger.error(FINAL, "", ex);
        } 
        catch (IOException ex) {
            logger.error(FINAL, "", ex);
        }        
    }
    
    @Override
    public void startDocument() throws SAXException{
        
    }
    
    @Override
    public void startElement( String uri, String localName, String qName, 
            Attributes attributes ) throws SAXException {        
        this.campo = qName;        
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)  
      throws SAXException {
        this.campo = null;
    }
    
    @Override
    public void characters(char ch[], int start, int length)  
      throws SAXException {        
        
        String info = new String(ch, start, length).trim();
        
        if(campo.equalsIgnoreCase("atualizacao")){
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            Date date = null;
            try {
                date = formatter.parse(info);
            } catch (ParseException ex) {
                logger.error("Error when parsing datetime for 'atualizacao' field", ex);
            }
            metar.setAtualizacao(date);
        }
        else if(campo.equalsIgnoreCase("pressao")){
            metar.setPressao(Double.parseDouble(info));
        }
        else if(campo.equalsIgnoreCase("temperatura")){
            metar.setTemperatura(Double.parseDouble(info));
        }
        else if(campo.equalsIgnoreCase("tempo_desc")){
            metar.setCondicaoTempo(info);
            if(info.toLowerCase().equals("chuvisco")){
                metar.setPrecipitacao(IntensidadeChuva.Chuvisco.getValor());
            }
            else if(info.toLowerCase().equals("chuva")){
                metar.setPrecipitacao(IntensidadeChuva.ChuvaModerada.getValor());
            }
        }
        else if(campo.equalsIgnoreCase("umidade")){
            metar.setUmidade(Integer.parseInt(info));
        }
        else if(campo.equalsIgnoreCase("vento_dir")){
            metar.setDirecaoVento(Double.parseDouble(info));
        }
        else if(campo.equalsIgnoreCase("vento_int")){
            metar.setVelocidadeVento(Converter.kilometerHourToMeterSecond(Double.parseDouble(info)));
        }
        else if(campo.equalsIgnoreCase("visibilidade")){
            metar.setVisibilidade(Integer.parseInt(info.replaceAll("[^0-9]", "")));
        }
    }
    
    public Metar getMetar(){
        return this.metar;
    }
    
}